pimpas.DOM.DragAndDrop = Class.create( );
pimpas.Extends(pimpas.DOM.DragAndDrop.prototype, pimpas.Object);
pimpas.Extends(pimpas.DOM.DragAndDrop.prototype,
	{
		initialize: function( el, target ) {
			this.log = new pimpas.Log();
			this.id = pimpas.globalID++;
			this.element = pimpas.DOM.getElement( el );
			this.target = pimpas.DOM.getElement( target );
		},
		element: null,
		clone: false,
		target: null,
		copyElement: null,
		appendTarget: false,
		dragEnabled: true,
		cursorDragEnabled: pimpas.DOM.Cursors.MOVE,
		cursorDragDisabled: pimpas.DOM.Cursors.DEFAULT,
		moveFirstAndChangeLater: false,
		dragInitFunction: null,
		dragMoveFunction: null,
		dragEndFunction: null,
		oldBottom: null,
		oldRight: null,
		oldPosition: null,
		oldZIndex: null,
		lastMouseX: null,
		lastMouseY: null,
		accessMoveableElement: function() {
			return (this.moveFirstAndChangeLater) ? this.copyElement : this.element;
		},
		initDrag: function() {
			this.dragEnabled = true;
			var obj = this;
			this.dragInitFunction = function(event) { obj.startDrag(event);};
			pimpas.DOM.Event.addListener( this.element, pimpas.DOM.Event.MOUSEDOWN, obj.dragInitFunction, false ); 
		},
		dragDropChangeCursor: function() {
			if(this.dragEnabled == true)
				pimpas.DOM.setCursor( this.accessMoveableElement(), this.cursorDragEnabled );
			else
				pimpas.DOM.setCursor( this.accessMoveableElement(), this.cursorDragDisabled );
		},
		startDrag: function(event) {
			event = pimpas.DOM.Event.fixEvent(event);
			var obj = this;
			
			if(this.moveFirstAndChangeLater) {
				this.copyElement = pimpas.DOM.clone( this.element );
				this.copyElement.setAttribute("id", this.element.id+"_clone");
				var styles = new Array();
				styles["position"]  = "relative";
				styles["bottom"] = pimpas.DOM.getDimensions(this.element).height + "px";
				styles["right"] = pimpas.DOM.getStyle( this.element, 'right' );
				pimpas.DOM.setStyle( this.copyElement, styles );
				pimpas.DOM.Filters.applyOpacity( this.copyElement, 0.300 );
				pimpas.DOM.add( document.body, this.copyElement);
			}
			
			pimpas.DOM.Event.removeListener( this.element, pimpas.DOM.Event.MOUSEDOWN, obj.dragInitFunction, false ); 
			pimpas.DOM.Event.addListener( this.accessMoveableElement() , pimpas.DOM.Event.MOSEUP, obj.endDrag, false ); 
			
			this.dragDropChangeCursor( true );
			var styles = new Array();
			var sourceElement = this.accessMoveableElement( );
			
			this.oldBottom 		=  pimpas.DOM.getStyle( sourceElement, 'bottom' );
			this.oldRight 		=  pimpas.DOM.getStyle( sourceElement, 'right' );
			this.oldPosition	=  pimpas.DOM.getStyle( sourceElement, 'position' );
			this.oldZIndex		=  pimpas.DOM.getStyle( sourceElement, 'zIndex' );
			
			if(pimpas.DOM.getStyle( sourceElement, 'bottom' ) == null || pimpas.DOM.getStyle( sourceElement, 'bottom' ) == '')
				styles["bottom"] = "0px";
			if(pimpas.DOM.getStyle( sourceElement, 'right' ) == null || pimpas.DOM.getStyle( sourceElement, 'right' ) == '')
				styles["right"] = "0px";
			styles["position"] = "relative";
			styles["zIndex"] = "999999";
			
			pimpas.DOM.setStyle(sourceElement, styles);
			
			this.dragMoveFunction = function(event) { obj.move(event); };	
			
			pimpas.DOM.Event.addListener( document, pimpas.DOM.Event.MOUSEMOVE, obj.dragMoveFunction, false );
			
			this.dragEndFunction = function(event) { obj.endDrag(event); };
			
			pimpas.DOM.Event.addListener( document, pimpas.DOM.Event.MOUSEUP, obj.dragEndFunction, false );
			
			this.lastMouseX = event.clientX;
			this.lastMouseY = event.clientY;
			
			// cancel out any text selections
			document.body.focus();
			// prevent text selection in IE
			document.onselectstart = function () { return false; };
			// prevent text selection (except IE)
			return false; 
		},
		endDrag: function(event) {
			var obj = this;
			
			pimpas.DOM.Event.removeListener( document, pimpas.DOM.Event.MOUSEMOVE, obj.dragMoveFunction, false );
			pimpas.DOM.Event.removeListener( document, pimpas.DOM.Event.MOUSEUP, obj.dragEndFunction, false );
			
			this.dragEnabled = false;
			this.dragDropChangeCursor( );
			
			
			var styles = new Array();
			styles["border"] = "0px";
			if(this.target != null)
				pimpas.DOM.setStyle( this.target, styles );
			
			// process last position
			var sourceElement = this.accessMoveableElement( );
			
			if(this.target != null) {
				if(pimpas.DOM.within( sourceElement, this.target )) {
					if(this.moveFirstAndChangeLater) {
						var st = new Array();
						pimpas.DOM.remove(sourceElement);
						if(this.appendTarget) {
							pimpas.DOM.remove(this.element);
							pimpas.DOM.add(this.target, this.element);
							return;
						}
						
						if(this.clone) {
							var c = pimpas.DOM.clone( this.element );	
							c.setAttribute( "id", this.element+"_clone" );
							this.dropElement( sourceElement, c);
							//pimpas.DOM.setStyle( c, st );
							pimpas.DOM.add( document.body, c );
						} else
							this.dropElement( sourceElement, this.element );
					} else {
							
					}
				} else {
					if(this.moveFirstAndChangeLater)
						pimpas.DOM.remove( sourceElement );
					else
						this.recoverStyles( );
				}
			} else {
				if(this.moveFirstAndChangeLater) {
					pimpas.DOM.remove(sourceElement);
					this.dropElement( sourceElement, this.element );
				}
			}
			
			this.initDrag( );
		},
		recoverStyles: function() {
			var styles = new Array();
			styles["bottom"] = this.oldBottom;
			styles["right"] = this.oldRight;
			styles["position"] = this.oldPosition;
			styles["zIndex"] = this.oldZIndex
			
			pimpas.DOM.setStyle( this.element, styles );
		},
		dropElement: function(source, el) {
			var y = parseInt(pimpas.DOM.getStyle(source, "bottom"));
			var x = parseInt(pimpas.DOM.getStyle(source, "right"));
			var st = new Array();
			st["position"] = "relative";
			st["bottom"] = (y-pimpas.DOM.getDimensions(this.element).height)+"px";
			st["zIndex"] = "9999";
			st["right"] = x+"px";
			
			pimpas.DOM.setStyle(el, st );
		},
		move: function(event) {
		    event = pimpas.DOM.Event.fixEvent(event);
			
			var sourceElement = this.accessMoveableElement( );
			
			var ey	= event.clientY;
			var ex	= event.clientX;
			var y = parseInt(pimpas.DOM.getStyle(sourceElement, "bottom"));
			var x = parseInt(pimpas.DOM.getStyle(sourceElement, "right"));
			var nx = x + ((ex - this.lastMouseX) * -1);
			var ny = y + ((ey - this.lastMouseY) * -1);
			
			// check conflict
			var styles = new Array();
			styles["border"] = "0px";
			
			if(this.target != null) {
				if(pimpas.DOM.within( sourceElement, this.target ))
					styles["border"] = "3px dotted black";
				
				pimpas.DOM.setStyle(this.target, styles);
			}
			
			styles = new Array();
			
			styles["right"] = nx + "px";
			styles["bottom"] = ny + "px";
			
			pimpas.DOM.setStyle( sourceElement, styles );
			
			this.lastMouseX = ex;
			this.lastMouseY = ey;
		}
	}
);